To be able to edit code and run cells, you need to run the notebook yourself. Where would you like to run the notebook?

In the cloud (experimental)

Binder is a free, open source service that runs scientific notebooks in the cloud! It will take a while, usually 2-7 minutes to get a session.

On your computer

(Recommended if you want to store your changes.)

  1. Copy the notebook URL:
  2. Run Pluto

    (Also see: How to install Julia and Pluto)

  3. Paste URL in the Open box

Frontmatter

If you are publishing this notebook on the web, you can set the parameters below to provide HTML metadata. This is useful for search engines and social media.

Author 1

Metaprogramming

(How to make Pluto)

👀 Reading hidden code
262 μs
Error message

The package Pluto.jl could not load because it failed to initialize.

That's not nice! Things you could try:

  • Restart the notebook.
  • Try a different Julia version.
  • Contact the developers of Pluto.jl about this error.

You might find useful information in the package installation log:

Be patient :)
👀 Reading hidden code
begin
import Pkg
import Pluto # before switching to the clean env
Pkg.activate(mktempdir())
Pkg.add(["PlutoUI"])
using PlutoUI
end
---

What is code?

👀 Reading hidden code
173 μs

Julia code comes in many forms. On its way from your thoughts to raw CPU instructions, the code undergoes a number of transformations. Every time that we go down a layer, we get to a structure that is more powerful and explicit, but less expressive.

  1. Thoughts in your head

  2. A text file with code (String)

  3. A syntax tree (Expr)

...

  1. CPU instructions

👀 Reading hidden code
595 μs

Syntax parsing

When you write Julia code, you do so by writing a text file. Try writing some Julia code in the box below!

👀 Reading hidden code
351 μs
Error message

UndefVarError: TextField not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. macro expansion
  2. Show more...
@bind test_code TextField((50, 5); default="""
x = let
# Let's do some math!
y=123
sqrt(y)
end""")
👀 Reading hidden code
---

Here is your code, in its original form, a String:

👀 Reading hidden code
200 μs
Error message

Another cell defining test_code contains errors.

test_code
👀 Reading hidden code
---
Error message

Another cell defining test_code contains errors.

Don't panic!
typeof(test_code)
👀 Reading hidden code
---
👀 Reading hidden code
67.3 μs

This is where we begin our story. The first thing that Julia does is syntax parsing: it goes from a String to an Expr.

👀 Reading hidden code
295 μs
Error message

Another cell defining test_code contains errors.

test_expr = parse_clean(test_code)
👀 Reading hidden code
---
Error message

Another cell defining test_code contains errors.

Oh no! 🙀
typeof(test_expr)
👀 Reading hidden code
---

That's right! Julia code is just another object in Julia! But what we see might be a little confusing: it is just the code that we typed, right?

👀 Reading hidden code
267 μs

Well, not exactly. What you see is Julia's built-in rich display, which does its best to make the Expr readable for us. The most readable way to display an abstract Expr is to show the equivalent code.

So instead, let's look directly at the internal structure of test_expr:

👀 Reading hidden code
293 μs
Error message

Another cell defining test_code contains errors.

computer bad, you GREAT!
sprint_dump(test_expr)
👀 Reading hidden code
---

Evaluation

👀 Reading hidden code
186 μs
Error message

UndefVarError: TextField not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. macro expansion
  2. Show more...
Be patient :)
@bind eval_code TextField((50, 5); default="""
x = let
# Let's do some math!
y=123
sqrt(y)
end""")
👀 Reading hidden code
---
Error message

Another cell defining eval_code contains errors.

Don't panic!
eval_expr = parse_clean(eval_code)
👀 Reading hidden code
---
Error message

Another cell defining eval_code contains errors.

let
🏡 = Module()
Core.eval(🏡, eval_expr)
end
👀 Reading hidden code
---

👀 Reading hidden code
67.8 μs




👀 Reading hidden code
113 μs
sprint_dump (generic function with 1 method)
function sprint_dump(x)
Text(sprint(Base.dump, x))
end
👀 Reading hidden code
443 μs
parse_clean (generic function with 1 method)
function parse_clean(code)
Base.remove_linenums!(Meta.parse(code, raise=false))
end
👀 Reading hidden code
593 μs